#include <iostream>
#include "Socket.hpp"
#include <poll.h>
#include <memory>
#include <algorithm>
using namespace LogModule;
#define NUM 1024
class PollServer
{
public:

    PollServer(int port)
        : _listen_socket(std::make_unique<TcpSocket>(port)), _isrunning(false)
    {
    }
    ~PollServer()
    {
        _listen_socket->Close();
    }
    void Init()
    {
        _listen_socket->BuildTcpSocket();
        for (int i = 0; i < NUM; i++)
        {
            _rfds[i].fd = -1;
            _rfds[i].events = 0;
            _rfds[i].revents = 0;
        }
        //先将LIstensockfd设置进辅助数组
        _rfds[0].fd = _listen_socket->Fd();
        _rfds[0].events = POLLIN;
    }
    void Start()
    {
        _isrunning = true;
        //
        while (_isrunning)
        {

            //阻塞式
            int n = poll(_rfds, NUM,-1);
            if (n > 0)
            {
                LOG(LogLevel::DEBUG) << "time out: ";
                Dispatcher();
                PrintRevents();
            }
            else if (n == 0)
            {
                LOG(LogLevel::DEBUG) << "time out....";
            }
            else
            {
                LOG(LogLevel::ERROR) << "poll error";
                return;
            }

            // InetAddr client;
            // int newsockfd = _listen_socket->Accept(&client);
            // LOG(LogLevel::DEBUG)<<"获得新连接: "<<newsockfd<<" "<<client.Ip()<<" "<<client.Port();
        }
        _isrunning = false;
    }
    void Dispatcher()
    {
        for (int i = 0; i < NUM; i++)
        {
            if (_rfds[i].fd == -1)
                continue;
            if (_rfds[i].fd == _listen_socket->Fd())
            {
                if (_rfds[i].revents&POLLIN)
                {
                    Accepter();
                }
            }
            else
            {
                if (_rfds[i].revents&POLLIN)
                {
                    Recv(i);
                }
                // if(_rfds[i].revents&POLLOUT)
                // {}
            }
        }
    }

    void Recv(int who)
    {
        char buffer[1024];
        int n = recv(_rfds[who].fd, buffer, sizeof(buffer) - 1, 0);
        if (n > 0)
        {
            buffer[n] = 0;
            std::cout << "client# " << buffer << std::endl;
            std::string message = "echo# ";
            message += buffer;
            send(_rfds[who].fd, message.c_str(), message.size(), 0);
        }
        else if (n == 0)
        {
            LOG(LogLevel::DEBUG) << "客户端退出," << _rfds[who].fd;
            close(_rfds[who].fd);
            _rfds[who].events = -1;
            _rfds[who].revents = -1;
        }
        else
        {
            LOG(LogLevel::DEBUG) << "recv error," << _rfds[who].fd;
            close(_rfds[who].fd);
            _rfds[who].events = -1;
            _rfds[who].revents = -1;
        }
    }
    void Accepter()
    {
        InetAddr client;
        int newsockfd = _listen_socket->Accept(&client);
        LOG(LogLevel::DEBUG) << "获得新连接: " << newsockfd << " " << client.Ip() << " " << client.Port();
        // recv()?就一定有数据吗？
        int pos = -1;
        for (int i = 0; i < NUM; i++)
        {
            if (_rfds[i].fd == -1)
            {
                pos = i;
                break;
            }
        }
        if (pos == -1)
        {
            LOG(LogLevel::DEBUG) << "服务器poll管理的fd满了扩容";
            //扩容
        }
        else
        {
            _rfds[pos].fd = newsockfd;
            _rfds[pos].events = POLLIN;
            //std::cout << "将newsockfd " << newsockfd << "设置进" << pos << " 辅助数组" << std::endl;
        }
    }
    void PrintRevents()
    {
        for(int i = 0;i<NUM;i++)
        {
            if(_rfds[i].fd==-1)
                continue;
            if(_rfds[i].revents!=0)
            {
                std::cout<<_rfds[i].fd<<"["<<ToRevents(_rfds[i].revents)<<"]  ";
            }
        }
        std::cout<<std::endl;
    }
    std::string ToRevents(int events)
    {
        if(events&POLLIN)
            return "POLLIN";
        if(events&POLLOUT)
            return "POLLOUT";
        return "";
    }
private:
    std::unique_ptr<Socket> _listen_socket;
    bool _isrunning;
    struct pollfd _rfds[NUM];// 辅助数组
};